using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;

namespace Cobalt75.GreyMatter
{
    public class GMQuery
    {
        internal GMQueryCommand pCommand;
        internal List<string> pTables;
        List<GMQueryClauseItemReference> pReturnColumns;
        List<GMQueryClauseItemReference> pGroupClauses;
        List<GMQueryClause> pSetClauses;
        List<GMQueryClause> pWhereClauses;
        Dictionary<string, object> pParameters;
        public GMQuery(GMQueryCommand command)
        {
            pCommand = command;
            pTables = new List<string>();
            pGroupClauses = new List<GMQueryClauseItemReference>();
            pReturnColumns = new List<GMQueryClauseItemReference>();
            pSetClauses = new List<GMQueryClause>();
            pWhereClauses = new List<GMQueryClause>();
            pParameters = new Dictionary<string, object>();

        }
        
        public GMQueryClauseItemReference[] ReturnColumns()
        {
            return (pReturnColumns.ToArray());

        }
        public GMQueryClauseItemReference[] GroupClauses()
        {
            return (pGroupClauses.ToArray());

        }
        public string[] Tables()
        {
            return (pTables.ToArray());

        }
        public Dictionary<string, object> Parameters()
        {
            return (pParameters);
        }
        public void SetParameter(string parameterName, object value)
        {
            pParameters[parameterName]=value;
        }
        public GMQueryClause[] SetClauses()
        {
            
                return (pSetClauses.ToArray());
            
        }
        public GMQueryClause[] WhereClauses()
        {
            return (pWhereClauses.ToArray());

        }
        public void AddTable(string tableName)
        {
            pTables.Add(tableName);
        }
        public void AddReturnColumns(GMQueryClauseItemReference itemReference)
        {
            pReturnColumns.Add(itemReference);
            if (itemReference.ReferenceType == GMQueryClauseItemReferenceType.Parameter)
            {
                pParameters.Add(itemReference.ParameterName, itemReference.ParameterValue);
            }
        }
        public void AddGroupClause(GMQueryClauseItemReference itemReference)
        {
            pGroupClauses.Add(itemReference);
            if (itemReference.ReferenceType == GMQueryClauseItemReferenceType.Parameter)
            {
                pParameters.Add(itemReference.ParameterName, itemReference.ParameterValue);
            }
        }
        public void AddWhereClauses(GMQueryClause clause)
        {
            pWhereClauses.Add(clause);
            if (clause.ItemA.ReferenceType == GMQueryClauseItemReferenceType.Parameter)
            {
                pParameters.Add(clause.ItemA.ParameterName, clause.ItemA.ParameterValue);
            }
            if (clause.ItemB.ReferenceType == GMQueryClauseItemReferenceType.Parameter)
            {
                pParameters.Add(clause.ItemB.ParameterName, clause.ItemB.ParameterValue);
            }
        }
        public void AddSetClauses(GMQueryClause clause)
        {
            pSetClauses.Add(clause);
            if (clause.ItemA.ReferenceType == GMQueryClauseItemReferenceType.Parameter)
            {
                pParameters.Add(clause.ItemA.ParameterName, clause.ItemA.ParameterValue);
            }
            if (clause.ItemB.ReferenceType == GMQueryClauseItemReferenceType.Parameter)
            {
                pParameters.Add(clause.ItemB.ParameterName, clause.ItemB.ParameterValue);
            }
        }
    }
    public enum GMQueryClauseItemReferenceType
    {
        Column,
        Function,
        Parameter,
        Literal
    }
    public struct GMQueryClauseItemReference
    {

        GMQueryClauseItemReferenceType pReferenceType;
        string pTableName;
        string pColumnName;
        string pColumnAlias;
        string pParameterName;
        object pParameterValue;
        string pFunctionFormatString;
        string pLiteralString;
        GMQuerySqlFunction pSqlFunction;
        List<GMQueryClauseItemReference> pFunctionParameters;

        public GMQueryClauseItemReferenceType ReferenceType
        {
            get
            {
                return pReferenceType;
            }
        }
        public string TableName
        {
            get
            {
                return pTableName;
            }
        }
        public string ColumnName
        {
            get
            {
                return pColumnName;
            }
        }
        public string ColumnAlias
        {
            get
            {
                return pColumnAlias;
            }
        }
        public string ParameterName
        {
            get
            {
                return pParameterName;
            }
        }
        public object ParameterValue
        {
            get
            {
                return pParameterValue;
            }
        }
        public string FunctionFormatString
        {
            get
            {
                return pFunctionFormatString;
            }
        }
        public string LiteralString
        {
            get
            {
                return pLiteralString;
            }
        }
        public GMQuerySqlFunction SqlFunction
        {
            get
            {
                return pSqlFunction;
            }
        }
        internal List<GMQueryClauseItemReference> FunctionParameters
        {
            get
            {
                return pFunctionParameters;
            }
        }


        public static GMQueryClauseItemReference All(string tableName)
        {
            GMQueryClauseItemReference iref = new GMQueryClauseItemReference();
            iref.pReferenceType = GMQueryClauseItemReferenceType.Column;
            iref.pTableName = tableName;
            iref.pColumnName = "*";
            return (iref);
        }
        public static GMQueryClauseItemReference Column(string tableName, string columnName)
        {
            GMQueryClauseItemReference iref = new GMQueryClauseItemReference();
            iref.pReferenceType = GMQueryClauseItemReferenceType.Column;
            iref.pTableName = tableName;
            iref.pColumnName = columnName;
            return (iref);
        }
        public static GMQueryClauseItemReference Column(string tableName, string columnName,string alias)
        {
            GMQueryClauseItemReference iref = new GMQueryClauseItemReference();
            iref.pReferenceType = GMQueryClauseItemReferenceType.Column;
            iref.pTableName = tableName;
            iref.pColumnName = columnName;
            iref.pColumnAlias = alias;
            return (iref);
        }
        public static GMQueryClauseItemReference Parameter(string parameterName, object parameterValue)
        {
            GMQueryClauseItemReference iref = new GMQueryClauseItemReference();
            iref.pReferenceType = GMQueryClauseItemReferenceType.Parameter;
            iref.pParameterName = parameterName;
            iref.pParameterValue = parameterValue;
            return (iref);
        }
        public static GMQueryClauseItemReference Function(string functionFormat)
        {
            GMQueryClauseItemReference iref = new GMQueryClauseItemReference();
            iref.pReferenceType = GMQueryClauseItemReferenceType.Function;
            iref.pFunctionFormatString = functionFormat;
            iref.pFunctionParameters = new List<GMQueryClauseItemReference>();
            return (iref);
        }
        public static GMQueryClauseItemReference Function(GMQuerySqlFunction sqlFunction)
        {
            GMQueryClauseItemReference iref = new GMQueryClauseItemReference();
            iref.pReferenceType = GMQueryClauseItemReferenceType.Function;
            iref.pSqlFunction = sqlFunction;
            iref.pFunctionParameters = new List<GMQueryClauseItemReference>();
            return (iref);
        }
        public static GMQueryClauseItemReference Literal(string text)
        {
            GMQueryClauseItemReference iref = new GMQueryClauseItemReference();
            iref.pReferenceType = GMQueryClauseItemReferenceType.Literal;
            iref.pLiteralString = text;
            return (iref);
        }
    }
    public enum GMQuerySqlFunction
    {
        StringConcatenate
    }
    public struct GMQueryClause
    {
        //public GMQClauseType ClauseType;
        GMQueryClauseOperator pClauseOperator;
        GMQueryClauseItemReference pItemA;
        GMQueryClauseItemReference pItemB;
        string pOtherFunctionFormat; // FIND_IN_SET({0},{1})

        public GMQueryClauseOperator ClauseOperator
        {
            get
            {
                return pClauseOperator;
            }
            set
            {
                pClauseOperator = value;
            }
        }
        public GMQueryClauseItemReference ItemA
        {
            get
            {
                return pItemA;
            }
            set
            {
                pItemA = value;
            }
        }
        public GMQueryClauseItemReference ItemB
        {
            get
            {
                return pItemB;
            }
            set
            {
                pItemB = value;
            }
        }
        public string OtherFunctionFormat
        {
            get
            {
                return pOtherFunctionFormat;
            }
            set
            {
                pOtherFunctionFormat = value;
            }
        }
   
    }
    public enum GMQueryClauseOperator
    {
        Equals,
        LessThan,
        GreaterThan,
        IsNot,
        IsNull,
        IsNotNull,
        FindInSet,
        Like,
        OtherFunction
    }
       
}
